//! Main library entry point for local_api_rust implementation.

#![allow(unused_imports)]

use async_trait::async_trait;
use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt};
use hyper::server::conn::Http;
use hyper::service::Service;
use log::info;
use std::future::Future;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll};
use swagger::{Has, XSpanIdString};
use swagger::auth::MakeAllowAllAuthenticator;
use swagger::EmptyContext;
use tokio::net::TcpListener;

#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};

use local_api_rust::models;

/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names
pub async fn create(addr: &str, https: bool) {
    let addr = addr.parse().expect("Failed to parse bind address");

    let server = Server::new();

    let service = MakeService::new(server);

    let service = MakeAllowAllAuthenticator::new(service, "cosmo");

    #[allow(unused_mut)]
    let mut service =
        local_api_rust::server::context::MakeAddContext::<_, EmptyContext>::new(
            service
        );

    if https {
        #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
        {
            unimplemented!("SSL is not implemented for the examples on MacOS, Windows or iOS");
        }

        #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
        {
            let mut ssl = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).expect("Failed to create SSL Acceptor");

            // Server authentication
            ssl.set_private_key_file("examples/server-key.pem", SslFiletype::PEM).expect("Failed to set private key");
            ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set certificate chain");
            ssl.check_private_key().expect("Failed to check private key");

            let tls_acceptor = ssl.build();
            let tcp_listener = TcpListener::bind(&addr).await.unwrap();

            loop {
                if let Ok((tcp, _)) = tcp_listener.accept().await {
                    let ssl = Ssl::new(tls_acceptor.context()).unwrap();
                    let addr = tcp.peer_addr().expect("Unable to get remote address");
                    let service = service.call(addr);

                    tokio::spawn(async move {
                        let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?;
                        let service = service.await.map_err(|_| ())?;

                        Http::new()
                            .serve_connection(tls, service)
                            .await
                            .map_err(|_| ())
                    });
                }
            }
        }
    } else {
        // Using HTTP
        hyper::server::Server::bind(&addr).serve(service).await.unwrap()
    }
}

#[derive(Copy, Clone)]
pub struct Server<C> {
    marker: PhantomData<C>,
}

impl<C> Server<C> {
    pub fn new() -> Self {
        Server{marker: PhantomData}
    }
}


use local_api_rust::{
    Api,
    HelloGetResponse,
    ProjectGetResponse,
    ShowGetResponse,
    MinappGetResponse,
    MinappMinappIdGetResponse,
    ProjectProjectIdBugAllGetResponse,
    ProjectProjectIdBugMyGetResponse,
    ProjectProjectIdBugRecordBugIdEventsGetResponse,
    ProjectProjectIdBugRecordBugIdShortNoteGetResponse,
    ProjectProjectIdBugRecordBugIdShowGetResponse,
    ProjectProjectIdCodeCommentCommentThreadIdCommentIdDeleteResponse,
    ProjectProjectIdCodeCommentCommentThreadIdCommentIdGetResponse,
    ProjectProjectIdCodeCommentCommentThreadIdCommentIdOptionsResponse,
    ProjectProjectIdCodeCommentCommentThreadIdCommentIdPostResponse,
    ProjectProjectIdCodeCommentCommentThreadIdGetResponse,
    ProjectProjectIdCodeCommentCommentThreadIdOptionsResponse,
    ProjectProjectIdCodeCommentCommentThreadIdPutResponse,
    ProjectProjectIdEntryFolderIdGetResponse,
    ProjectProjectIdEntryShowEntryIdGetResponse,
    ProjectProjectIdEventGetResponse,
    ProjectProjectIdEventOptionsResponse,
    ProjectProjectIdEventPostResponse,
    ProjectProjectIdTaskAllGetResponse,
    ProjectProjectIdTaskMyGetResponse,
    ProjectProjectIdTaskRecordTaskIdDependGetResponse,
    ProjectProjectIdTaskRecordTaskIdEventsGetResponse,
    ProjectProjectIdTaskRecordTaskIdShortNoteGetResponse,
    ProjectProjectIdTaskRecordTaskIdShowGetResponse,
    ProjectProjectIdTaskRecordTaskIdSubTaskGetResponse,
    ProjectProjectIdToolsPostHookGetResponse,
};
use local_api_rust::server::MakeService;
use std::error::Error;
use swagger::ApiError;

#[async_trait]
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
{
    /// 握手协议
    async fn hello_get(
        &self,
        access_token: String,
        context: &C) -> Result<HelloGetResponse, ApiError>
    {
        info!("hello_get(\"{}\") - X-Span-ID: {:?}", access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 获取项目列表
    async fn project_get(
        &self,
        access_token: String,
        context: &C) -> Result<ProjectGetResponse, ApiError>
    {
        info!("project_get(\"{}\") - X-Span-ID: {:?}", access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 显示软件桌面
    async fn show_get(
        &self,
        access_token: String,
        context: &C) -> Result<ShowGetResponse, ApiError>
    {
        info!("show_get(\"{}\") - X-Span-ID: {:?}", access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 列出微应用
    async fn minapp_get(
        &self,
        access_token: String,
        context: &C) -> Result<MinappGetResponse, ApiError>
    {
        info!("minapp_get(\"{}\") - X-Span-ID: {:?}", access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 显示微应用
    async fn minapp_minapp_id_get(
        &self,
        minapp_id: String,
        access_token: String,
        context: &C) -> Result<MinappMinappIdGetResponse, ApiError>
    {
        info!("minapp_minapp_id_get(\"{}\", \"{}\") - X-Span-ID: {:?}", minapp_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 所有缺陷
    async fn project_project_id_bug_all_get(
        &self,
        project_id: String,
        offset: i32,
        limit: i32,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdBugAllGetResponse, ApiError>
    {
        info!("project_project_id_bug_all_get(\"{}\", {}, {}, \"{}\") - X-Span-ID: {:?}", project_id, offset, limit, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 指派给我的缺陷
    async fn project_project_id_bug_my_get(
        &self,
        project_id: String,
        access_token: String,
        state: String,
        context: &C) -> Result<ProjectProjectIdBugMyGetResponse, ApiError>
    {
        info!("project_project_id_bug_my_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, access_token, state, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 缺陷相关事件
    async fn project_project_id_bug_record_bug_id_events_get(
        &self,
        project_id: String,
        bug_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdBugRecordBugIdEventsGetResponse, ApiError>
    {
        info!("project_project_id_bug_record_bug_id_events_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, bug_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 便签方式显示缺陷
    async fn project_project_id_bug_record_bug_id_short_note_get(
        &self,
        project_id: String,
        bug_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdBugRecordBugIdShortNoteGetResponse, ApiError>
    {
        info!("project_project_id_bug_record_bug_id_short_note_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, bug_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 显示缺陷
    async fn project_project_id_bug_record_bug_id_show_get(
        &self,
        project_id: String,
        bug_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdBugRecordBugIdShowGetResponse, ApiError>
    {
        info!("project_project_id_bug_record_bug_id_show_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, bug_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 删除代码评论
    async fn project_project_id_code_comment_comment_thread_id_comment_id_delete(
        &self,
        project_id: String,
        comment_thread_id: String,
        comment_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdCodeCommentCommentThreadIdCommentIdDeleteResponse, ApiError>
    {
        info!("project_project_id_code_comment_comment_thread_id_comment_id_delete(\"{}\", \"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, comment_thread_id, comment_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 获取单个代码评论
    async fn project_project_id_code_comment_comment_thread_id_comment_id_get(
        &self,
        project_id: String,
        comment_thread_id: String,
        comment_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdCodeCommentCommentThreadIdCommentIdGetResponse, ApiError>
    {
        info!("project_project_id_code_comment_comment_thread_id_comment_id_get(\"{}\", \"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, comment_thread_id, comment_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// cors helper
    async fn project_project_id_code_comment_comment_thread_id_comment_id_options(
        &self,
        project_id: String,
        comment_thread_id: String,
        comment_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdCodeCommentCommentThreadIdCommentIdOptionsResponse, ApiError>
    {
        info!("project_project_id_code_comment_comment_thread_id_comment_id_options(\"{}\", \"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, comment_thread_id, comment_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 更新单个代码评论
    async fn project_project_id_code_comment_comment_thread_id_comment_id_post(
        &self,
        project_id: String,
        comment_thread_id: String,
        comment_id: String,
        access_token: String,
        project_project_id_code_comment_comment_thread_id_put_request: Option<models::ProjectProjectIdCodeCommentCommentThreadIdPutRequest>,
        context: &C) -> Result<ProjectProjectIdCodeCommentCommentThreadIdCommentIdPostResponse, ApiError>
    {
        info!("project_project_id_code_comment_comment_thread_id_comment_id_post(\"{}\", \"{}\", \"{}\", \"{}\", {:?}) - X-Span-ID: {:?}", project_id, comment_thread_id, comment_id, access_token, project_project_id_code_comment_comment_thread_id_put_request, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 列出代码评论
    async fn project_project_id_code_comment_comment_thread_id_get(
        &self,
        project_id: String,
        comment_thread_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdCodeCommentCommentThreadIdGetResponse, ApiError>
    {
        info!("project_project_id_code_comment_comment_thread_id_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, comment_thread_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// cors helper
    async fn project_project_id_code_comment_comment_thread_id_options(
        &self,
        project_id: String,
        comment_thread_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdCodeCommentCommentThreadIdOptionsResponse, ApiError>
    {
        info!("project_project_id_code_comment_comment_thread_id_options(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, comment_thread_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 新增代码评论
    async fn project_project_id_code_comment_comment_thread_id_put(
        &self,
        project_id: String,
        comment_thread_id: String,
        access_token: String,
        project_project_id_code_comment_comment_thread_id_put_request: Option<models::ProjectProjectIdCodeCommentCommentThreadIdPutRequest>,
        context: &C) -> Result<ProjectProjectIdCodeCommentCommentThreadIdPutResponse, ApiError>
    {
        info!("project_project_id_code_comment_comment_thread_id_put(\"{}\", \"{}\", \"{}\", {:?}) - X-Span-ID: {:?}", project_id, comment_thread_id, access_token, project_project_id_code_comment_comment_thread_id_put_request, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 列出内容目录和入口
    async fn project_project_id_entry_folder_id_get(
        &self,
        project_id: String,
        folder_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdEntryFolderIdGetResponse, ApiError>
    {
        info!("project_project_id_entry_folder_id_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, folder_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 打开内容入口
    async fn project_project_id_entry_show_entry_id_get(
        &self,
        project_id: String,
        entry_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdEntryShowEntryIdGetResponse, ApiError>
    {
        info!("project_project_id_entry_show_entry_id_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, entry_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 事件列表
    async fn project_project_id_event_get(
        &self,
        project_id: String,
        from_time: i64,
        to_time: i64,
        offset: i32,
        limit: i32,
        access_token: String,
        user_id: Option<String>,
        context: &C) -> Result<ProjectProjectIdEventGetResponse, ApiError>
    {
        info!("project_project_id_event_get(\"{}\", {}, {}, {}, {}, \"{}\", {:?}) - X-Span-ID: {:?}", project_id, from_time, to_time, offset, limit, access_token, user_id, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// cors helper
    async fn project_project_id_event_options(
        &self,
        project_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdEventOptionsResponse, ApiError>
    {
        info!("project_project_id_event_options(\"{}\", \"{}\") - X-Span-ID: {:?}", project_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 上报自定义事件
    async fn project_project_id_event_post(
        &self,
        project_id: String,
        access_token: String,
        project_project_id_event_post_request: Option<models::ProjectProjectIdEventPostRequest>,
        context: &C) -> Result<ProjectProjectIdEventPostResponse, ApiError>
    {
        info!("project_project_id_event_post(\"{}\", \"{}\", {:?}) - X-Span-ID: {:?}", project_id, access_token, project_project_id_event_post_request, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 所有任务
    async fn project_project_id_task_all_get(
        &self,
        project_id: String,
        offset: i32,
        limit: i32,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdTaskAllGetResponse, ApiError>
    {
        info!("project_project_id_task_all_get(\"{}\", {}, {}, \"{}\") - X-Span-ID: {:?}", project_id, offset, limit, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 指派给我的任务
    async fn project_project_id_task_my_get(
        &self,
        project_id: String,
        state: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdTaskMyGetResponse, ApiError>
    {
        info!("project_project_id_task_my_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, state, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 列出依赖工单
    async fn project_project_id_task_record_task_id_depend_get(
        &self,
        project_id: String,
        task_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdTaskRecordTaskIdDependGetResponse, ApiError>
    {
        info!("project_project_id_task_record_task_id_depend_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, task_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 任务相关事件
    async fn project_project_id_task_record_task_id_events_get(
        &self,
        project_id: String,
        task_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdTaskRecordTaskIdEventsGetResponse, ApiError>
    {
        info!("project_project_id_task_record_task_id_events_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, task_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 便签方式显示任务
    async fn project_project_id_task_record_task_id_short_note_get(
        &self,
        project_id: String,
        task_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdTaskRecordTaskIdShortNoteGetResponse, ApiError>
    {
        info!("project_project_id_task_record_task_id_short_note_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, task_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 显示任务
    async fn project_project_id_task_record_task_id_show_get(
        &self,
        project_id: String,
        task_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdTaskRecordTaskIdShowGetResponse, ApiError>
    {
        info!("project_project_id_task_record_task_id_show_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, task_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// 列出子任务
    async fn project_project_id_task_record_task_id_sub_task_get(
        &self,
        project_id: String,
        task_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdTaskRecordTaskIdSubTaskGetResponse, ApiError>
    {
        info!("project_project_id_task_record_task_id_sub_task_get(\"{}\", \"{}\", \"{}\") - X-Span-ID: {:?}", project_id, task_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

    /// git post commit hook回调
    async fn project_project_id_tools_post_hook_get(
        &self,
        project_id: String,
        access_token: String,
        context: &C) -> Result<ProjectProjectIdToolsPostHookGetResponse, ApiError>
    {
        info!("project_project_id_tools_post_hook_get(\"{}\", \"{}\") - X-Span-ID: {:?}", project_id, access_token, context.get().0.clone());
        Err(ApiError("Generic failure".into()))
    }

}
